package grad.nxu.recruitsystem.controller;

import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import grad.nxu.recruitsystem.domain.Admin;
import grad.nxu.recruitsystem.domain.Hr;
import grad.nxu.recruitsystem.domain.Seeker;
import grad.nxu.recruitsystem.domain.UserRole;
import grad.nxu.recruitsystem.dto.User;
import grad.nxu.recruitsystem.enums.Role;
import grad.nxu.recruitsystem.service.*;
import grad.nxu.recruitsystem.util.EmailUtil;
import grad.nxu.recruitsystem.util.JWTUtil;
import grad.nxu.recruitsystem.vo.ApiResponse;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.Duration;
import java.util.Random;

/**
 * @Author: HAPPY
 * @Project_name: recruitSystem
 * @Package_name: grad.nxu.recruitsystem.controller
 * @Date: 2023/3/10 15:49
 * @Description:
 */
@RestController
@RequestMapping("/api/v1")
public class AuthenticationController {
    @Autowired
    StringRedisTemplate stringRedisTemplate;
    @Autowired
    SeekerService seekerService;
    @Autowired
    HrService hrService;
    @Autowired
    AdminService adminService;
    @Autowired
    AuthenticationService authenticationService;
    @Autowired
    UserRoleService userRoleService;
    @Autowired
    EmailUtil emailUtil;

    /**
     * 登录接口
     *
     * @param user 登录用户信息
     * @return 返回的data是登录后的用户信息，含token
     */
    @ApiOperation("登录接口")
    @PostMapping("/login")
    public ApiResponse<User> login(User user) {
        ApiResponse<User> apiResponse = new ApiResponse<>();
        // 判空
        if (user == null || user.getEmail() == null || user.getPassword() == null) {
            apiResponse.setSuccess(false).setCode(403).setMessage("账号或密码错误");
        } else {
            ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
            // 密码加密
            user.setPassword(SecureUtil.sha256(user.getPassword()));

            // 判断身份
            if ("求职者".equals(user.getRoleName())) {
                User loginSeeker = seekerService.login(user);
                if (loginSeeker != null) {
                    if (loginSeeker.getStatus()) {
                        user = loginSeeker;
                    } else {
                        apiResponse.setCode(403).setMessage("该账号已被封禁！").setSuccess(false);
                        return apiResponse;
                    }
                }
            } else {
                if ("招聘者".equals(user.getRoleName())) {
                    User loginHr = hrService.login(user);
                    if (loginHr != null) {
                        if (loginHr.getStatus()) {
                            user = loginHr;
                        } else {
                            apiResponse.setCode(403).setMessage("该账号已被封禁！").setSuccess(false);
                            return apiResponse;
                        }
                    }
                } else {
                    User loginAdmin = adminService.login(user);
                    if (loginAdmin != null) {
                       user = loginAdmin;
                    }
                }
            }

            // 如果登录成功, 授予令牌
            if (user.getId() != null) {
                // 利用用户邮箱生成token
                String token = JWTUtil.getToken(user.getId(), user.getName(), user.getEmail(), user.getRoleId());
                // java.time.Duration.ofSeconds(long seconds)方法获取表示秒数的Duration和以纳秒为单位的调整。
                operations.set("recruit:token:" + user.getEmail(), token, Duration.ofSeconds(120 * 60));
                apiResponse.setData(user.setToken(token)).setCode(200).setMessage("登录成功").setSuccess(true);
                System.out.println(token);
            } else {
                apiResponse.setSuccess(false).setCode(500).setMessage("账号或密码错误");
            }
        }

        return apiResponse;
    }

    /**
     * 获取验证码接口
     *
     * @param email 接受验证码的邮箱
     * @param use   用途，注册|重置
     * @return 返回发送结果
     */
    @ApiOperation("获取注册验证码")
    @PostMapping("/register/captcha")
    public ApiResponse<String> getCaptcha(String email, String use) {
        ApiResponse<String> apiResponse = new ApiResponse<>();
        if (email == null) {
            apiResponse.setSuccess(false).setMessage("请输入邮箱！").setCode(500);
        } else {
            if ("注册".equals(use)) {
                if (!authenticationService.isRegistered(email)) {
                    // 发送验证码
                    Random random = new Random();
                    String captcha = String.valueOf(random.nextInt(1000000));
                    // 新建线程发送验证码
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            emailUtil.sendEmail(email, "【职汇】注册验证码", "您的注册验证码是: " + captcha + "，有效期五分钟。");
                        }
                    }).start();

                    // 将验证码放入redis缓存，有效期5分钟
                    stringRedisTemplate.opsForValue().set("recruit:captcha:register:" + email, captcha, Duration.ofSeconds(60 * 5));
                    apiResponse.setCode(200).setMessage("验证码发送成功！").setSuccess(true);
                } else {
                    apiResponse.setCode(403).setSuccess(false).setMessage("该邮箱已被注册");
                }
            } else {
                if (authenticationService.isRegistered(email)) {
                    // 发送验证码
                    Random random = new Random();
                    String captcha = String.valueOf(random.nextInt(1000000));
                    // 新建线程发送验证码
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            emailUtil.sendEmail(email, "【职汇】重置密码验证", "您的重置密码验证码是: " + captcha + "，有效期五分钟。");
                        }
                    }).start();

                    // 将验证码放入redis缓存，有效期5分钟
                    stringRedisTemplate.opsForValue().set("recruit:captcha:reset:" + email, captcha, Duration.ofSeconds(60 * 5));
                    apiResponse.setCode(200).setMessage("验证码发送成功！").setSuccess(true);
                } else {
                    apiResponse.setCode(403).setSuccess(false).setMessage("该邮箱尚未注册");
                }
            }
        }

        return apiResponse;
    }

    /**
     * 注册接口
     *
     * @param user 注册用户信息
     * @return 返回注册结果
     */
    @ApiOperation("注册接口")
    @PostMapping("/register")
    public ApiResponse<Seeker> register(User user) {
        ApiResponse<Seeker> apiResponse = new ApiResponse<>();

        if (user == null || user.getEmail() == null || user.getPassword() == null || user.getCaptcha() == null) {
            apiResponse.setMessage("请输入信息！").setSuccess(false).setCode(500);
        } else {
            // 查询该邮箱是否已经注册
            if (!authenticationService.isRegistered(user.getEmail())) {
                // 查询验证码
                String captcha = stringRedisTemplate.opsForValue().get("recruit:captcha:register:" + user.getEmail());
                if (captcha != null && captcha.equals(user.getCaptcha())) {
                    if ("求职者".equals(user.getRoleName())) {
                        Seeker seeker = new Seeker().setPassword(SecureUtil.sha256(user.getPassword())).setEmail(user.getEmail()).setRole(Role.SEEKER.getRoleId());
                        seekerService.save(seeker);
                        userRoleService.save(new UserRole().setUserEmail(user.getEmail()).setRoleId(Role.SEEKER.getRoleId()));
                    } else {
                        Hr hr = new Hr().setPassword(SecureUtil.sha256(user.getPassword())).setEmail(user.getEmail()).setRole(Role.HR.getRoleId());
                        hrService.save(hr);
                        userRoleService.save(new UserRole().setUserEmail(user.getEmail()).setRoleId(Role.HR.getRoleId()));
                    }

                    apiResponse.setCode(200).setMessage("注册成功！").setSuccess(true);
                } else {
                    apiResponse.setCode(403).setSuccess(false).setMessage("验证码错误");
                }
            } else {
                apiResponse.setCode(403).setSuccess(false).setMessage("该邮箱已被注册");
            }
        }

        return apiResponse;
    }

    /**
     * 重置密码接口
     *
     * @param user 用户信息
     * @return 返回重置结果
     */
    @ApiOperation("重置密码接口")
    @PostMapping("/resetpassword")
    public ApiResponse<String> resetPassword(User user) {
        ApiResponse<String> apiResponse = new ApiResponse<>();
        boolean flag = false;
        // 判空
        if (user == null || user.getEmail() == null || user.getCaptcha() == null) {
            apiResponse.setSuccess(false).setCode(403).setMessage("请输入邮箱");
        } else {
            // 获取验证码
            String captcha = stringRedisTemplate.opsForValue().get("recruit:captcha:reset:" + user.getEmail());

            if (captcha != null && captcha.equals(user.getCaptcha())) {
                user.setPassword(SecureUtil.sha256(user.getPassword()));
                if ("求职人员".equals(user.getRoleName())) {
                    if (seekerService.modifyPassword(user.getEmail(), user.getPassword()) == 1) {
                        flag = true;
                    }
                } else {
                    if ("招聘人员".equals(user.getRoleName())) {
                        if (hrService.modifyPassword(user.getEmail(), user.getPassword()) == 1) {
                            flag = true;
                        }
                    } else {
                        if (adminService.modifyPassword(user.getEmail(), user.getPassword()) == 1) {
                            flag = true;
                        }
                    }
                }
            }
        }
        if (flag) {
            apiResponse.setCode(200).setSuccess(true).setMessage("重置密码成功！");
        } else {
            apiResponse.setCode(500).setSuccess(false).setMessage("验证码错误");
        }

        return apiResponse;
    }

    /**
     * 求职者认证接口
     * @param id 求职者id
     * @return 认证结果
     */
    @ApiOperation("求职者认证接口")
    @PutMapping("/admin/auth/seeker")
    public ApiResponse<String> authSeeker(Integer id) {
        ApiResponse<String> apiResponse = new ApiResponse<>();
        UpdateWrapper<Seeker> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set("is_attestation", true);
        updateWrapper.eq("id", id);
        try {
            seekerService.update(null, updateWrapper);
            apiResponse.setCode(200).setSuccess(true).setMessage("认证成功");
        } catch (Exception e) {
            apiResponse.setCode(500).setSuccess(false).setMessage("认证失败");
        }

        return apiResponse;
    }

    /**
     * 招聘者认证接口
     * @param id 招聘者id
     * @return 认证结果
     */
    @ApiOperation("求职者认证接口")
    @PutMapping("/admin/auth/hr")
    public ApiResponse<String> authHr(Integer id) {
        ApiResponse<String> apiResponse = new ApiResponse<>();
        UpdateWrapper<Hr> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set("is_attestation", true);
        updateWrapper.eq("id", id);
        try {
            hrService.update(null, updateWrapper);
            apiResponse.setCode(200).setSuccess(true).setMessage("认证成功");
        } catch (Exception e) {
            apiResponse.setCode(500).setSuccess(false).setMessage("认证失败");
        }

        return apiResponse;
    }
    /**
     * 求职者取消认证接口
     * @param id 求职者id
     * @return 认证结果
     */
    @ApiOperation("求职者取消认证接口")
    @PutMapping("/admin/unauth/seeker")
    public ApiResponse<String> unAuthSeeker(Integer id) {
        ApiResponse<String> apiResponse = new ApiResponse<>();
        UpdateWrapper<Seeker> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set("is_attestation", false);
        updateWrapper.eq("id", id);
        try {
            seekerService.update(null, updateWrapper);
            apiResponse.setCode(200).setSuccess(true).setMessage("认证成功");
        } catch (Exception e) {
            apiResponse.setCode(500).setSuccess(false).setMessage("认证失败");
        }

        return apiResponse;
    }

    /**
     * 招聘者取消认证接口
     * @param id 招聘者id
     * @return 认证结果
     */
    @ApiOperation("求职者认证接口")
    @PutMapping("/admin/unauth/hr")
    public ApiResponse<String> unAuthHr(Integer id) {
        ApiResponse<String> apiResponse = new ApiResponse<>();
        UpdateWrapper<Hr> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set("is_attestation", false);
        updateWrapper.eq("id", id);
        try {
            hrService.update(null, updateWrapper);
            apiResponse.setCode(200).setSuccess(true).setMessage("认证成功");
        } catch (Exception e) {
            apiResponse.setCode(500).setSuccess(false).setMessage("认证失败");
        }

        return apiResponse;
    }
}
